﻿using System.Text;
using Devonline.AspNetCore;
using Devonline.Communication.Messages;
using Devonline.Core;
using Devonline.Entity;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Serilog;

var builder = WebApplication.CreateBuilder(args);
builder.Host.UseSerilog((context, logger) => logger.ReadFrom.Configuration(context.Configuration));
builder.AddCommunicator();

var services = builder.Services;
services.AddLogging();

var app = builder.Build();
await app.StartAsync();

var logger = app.Services.GetService<ILogger<Program>>();
var communicator = app.Services.GetService<IMessageCommunicator>();
if (communicator != null && logger != null)
{
    try
    {
        Message? _message = null;
        communicator.Connected += (sender, e) =>
        {
            logger.LogWarning("通讯器已经启动");
            logger.LogInformation("输入 {command} 退出", "quit");
            logger.LogInformation("输入 {command} 将最后一条收到的消息标记为已读", "read");
            logger.LogInformation("输入 {type}#{content}@{receiver} 形式将发送指定类型的消息内容给指定接收者", "消息类型", "消息内容", "接收者");
            logger.LogInformation("可以输入以上三种形式的两种组合, 未输入 {receiver} 将一律视为默认接收者", "接收者");
            logger.LogInformation("输入其余任意内容将视为文本消息内容发送给默认接收者");
        };

        communicator.Receive += async (sender, message) =>
        {
            _message = message;
            if (message.Type == MessageType.File)
            {
                var fileName = $"/home/app/dcs/file-{KeyGenerator.GetKey()}.zip";
                logger.LogInformation("收到来自: {sender} 的文件消息, 将保存文件到默认目录: {file}", message.Sender, fileName);
                var data = Encoding.UTF8.GetBytes(message.Content ?? string.Empty);
                await File.WriteAllBytesAsync(fileName, data);
            }
            else
            {
                logger.LogInformation("收到来自: {sender} 的 {type} 类型的消息: {content}", message.Sender, message.Type, message.Content);
            }
        };

        await communicator.StartAsync();
        var input = Console.ReadLine();
        while (input != "quit")
        {
            if (!string.IsNullOrWhiteSpace(input))
            {
                try
                {
                    var array = input.Split(AppSettings.CHAR_SHARP, AppSettings.CHAR_AT);
                    switch (array.Length)
                    {
                        case 2:
                            if (input.Contains(AppSettings.CHAR_AT))
                            {
                                //content@receiver 形式
                                await communicator.SendAsync(array[0], array[1]);
                            }
                            else
                            {
                                //type#content 形式
                                await communicator.SendAsync(array[1], Enum.Parse<MessageType>(array[0].FirstCharToUpper()));
                            }
                            break;
                        case 3:
                            //type#content@receiver 形式
                            await communicator.SendAsync(array[1], array[2], Enum.Parse<MessageType>(array[0].FirstCharToUpper()));
                            break;
                        default:
                            if (Enum.TryParse(input.FirstCharToUpper(), true, out MessageType type))
                            {
                                if (type == MessageType.Read && _message != null)
                                {
                                    //消息已读形式
                                    await communicator.ReadAsync(_message.Id);
                                    _message = null;
                                }
                                else
                                {
                                    //指令形式
                                    await communicator.ExecuteAsync(type);
                                }
                            }
                            else
                            {
                                //纯文本形式
                                await communicator.SendAsync(input);
                            }
                            break;
                    }
                }
                catch (Exception ex)
                {
                    logger.LogWarning("通讯器输入处理异常: " + ex.GetMessage());
                }
            }

            input = Console.ReadLine();
        }

        await communicator.StopAsync();
    }
    catch (Exception ex)
    {
        logger.LogError(ex, "客户端链接出错, {message}", ex.GetInnerException());
    }

    await app.StopAsync();
    logger.LogInformation("客户端退出, 消息中心连接结束!");
}